﻿using System;
using System.Drawing;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;

using Color = Microsoft.Xna.Framework.Color;
using Vector4 = Microsoft.Xna.Framework.Vector4;
using SysColor = System.Drawing.Color;

namespace MaterialEditor
{
    public enum NodeValueType
    {
        ValueFloat,
        ValueTexture,
        ValueColor,
        ValueVector2,
        ValueVector3,
    }

    public partial class NodeValue
    {
        TemporalValue value;
        public object Value
        {
            get { return value.Value; }

            set 
            {
                // if the value does not exist, create it
                if (this.value == null)
                    this.value = new TemporalValue();
                this.value.Value = value;
                if (ValueChanged != null)
                    ValueChanged();
            }
        }

        public NodeValueType type
        {
            get { return value.type; }
        }

        public event BasicDelegate ValueChanged;
        public event BasicDelegate TimeChanged;

        public NodeValue(float value)
        {
            this.value = value;
            this.value.ValueChanged += value_ValueChanged;

        }
        public NodeValue(TextureContainer value)
        {
            Texture2D tex = value.texture.Material;

            value.texture.Dispose();
            TextureContainer container = new TextureContainer(tex);

            Value = container;
            this.value.To<TextureContainer>().texture.effects += value.texture.effects;
            this.value.type = NodeValueType.ValueTexture;
            this.value.ValueChanged += value_ValueChanged;
        }
        public NodeValue(Color value)
        {
            this.value = value;
            this.value.ValueChanged += value_ValueChanged;
        }

        void value_ValueChanged()
        {
            if (TimeChanged != null)
                TimeChanged();
        }

        public NodeValue(Vector2 value)
        {
            this.value = value;
            this.value.ValueChanged += value_ValueChanged;
        }

        public NodeValue(Vector3 value)
        {
            this.value = value;
            this.value.ValueChanged += value_ValueChanged;
        }

        public NodeValue(NodeValue other)
        {
            if (other.type == NodeValueType.ValueTexture)
            {
                Texture2D tex = other.AsTexture2D();
                
                Value = new TextureContainer(tex);
                this.value.To<TextureContainer>().texture.effects += other.value.To<TextureContainer>().texture.effects;
                this.value.type = NodeValueType.ValueTexture;
            }
            else if (other.type == NodeValueType.ValueColor)
                Value = (Color)other.value.To<Color>();
            else if (other.type == NodeValueType.ValueFloat)
                Value = other.value.To<float>();
            else if (other.type == NodeValueType.ValueVector2)
                Value = other.value.To<Vector2>();
            else if (other.type == NodeValueType.ValueVector3)
                Value = other.value.To<Vector3>();

            //this.value.ValueChanged += value_ValueChanged;
        }

        public NodeValue(object value)
        {
            Value = value;
            //this.value.ValueChanged += value_ValueChanged;
        }

        public Color AsColor()
        {
            return value.To<Color>();
        }
        public Texture2D AsTexture2D()
        {
            return value.To<TextureContainer>().texture.Material;
        }
        public Vector2 AsVector2()
        {
            return value.To<Vector2>();
        }
        public Vector3 AsVector3()
        {
            return value.To<Vector3>();
        }
        public float AsFloat()
        {
            return value.To<float>();
        }
        public TextureContainer AsTextureContainer()
        {
            return value.To<TextureContainer>();
        }


        public const int textureRectDim = 250;

        public void Draw(int x, int y)
        {
            Graphics graphics = Graphics.Instance;
            
            switch (type)
            {
                case NodeValueType.ValueFloat:
                    graphics.DrawText(new Vector2(x, y) - Fonts.fonts["Arial"].MeasureString(Value.ToString()) / 2.0f, Fonts.fonts["Arial"], Value.ToString(), System.Drawing.Color.Black);
                    break;
                case NodeValueType.ValueColor:
                    Color c = (Color)Value;
                    graphics.DrawRect(new System.Drawing.Rectangle(x - 5, y - 5, 10, 10), SysColor.FromArgb(c.A, c.R, c.G, c.B));
                    break;
                case NodeValueType.ValueTexture:
                    value.To<TextureContainer>().texture.Draw(new Vector2(x - textureRectDim / 2, y - textureRectDim / 2), new Vector2(textureRectDim),
                        value.To<TextureContainer>().texture.effects.TexCoords);
                    break;
                case NodeValueType.ValueVector2:
                    graphics.DrawText(new Vector2(x, y) - Fonts.fonts["Arial"].MeasureString(Value.ToString()) / 2.0f, Fonts.fonts["Arial"], Value.ToString(), SysColor.Black);
                    break;
                case NodeValueType.ValueVector3:
                    graphics.DrawText(new Vector2(x, y) - Fonts.fonts["Arial"].MeasureString(Value.ToString()) / 2.0f, Fonts.fonts["Arial"], Value.ToString(), SysColor.Black);
                    break;
            }
        }
    }
}